package com.xielun.fly.framework;

import net.minidev.json.JSONValue;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


/**
 * 飞跃引擎，非同凡响
 * 所有的业务操作，可以归纳成一个个的sql节点形成的一个树形结构，每个sql节点代表着一种增删改查操作
 * 由 json 描述这个树，引擎将json第一遍解析为node tree,第二遍执行树的节点
 */
public class FlyEngine {
    private Node root; //跟节点

    public static void main(String[] args) {
        //String json = "{'user[]':{'book':{'@column':'id','user_id':'@/user[]/id'}}}";
       // String json = "{'user[]':{'book':{'@column':'id','user_id':'@../id','id':'@/user[]/id'},'sex':2,'@order':'id-,sex'}}";
        String json = "{'+user':{'id':132,'$sex':1,'$name':'kalllx'}}";


        System.out.println(JSONValue.toJSONString(new FlyEngine().fly(json).getData()));


    }

    /**
     * 引擎启动方法
     *
     * @param json 业务json
     * @return 跟节点
     */
    public Node fly(String json) {
        root = new Node();
        root.setKey("root");
        root.setData(new LinkedHashMap());
        Map<String, Object> obj = (Map<String, Object>) JSONValue.parseKeepingOrder(json);
        parseNode(root, obj);
        fillData(root);

        return root;
    }

    /**
     * 解析node节点
     *
     * @param pNode 父节点
     * @param obj   {}
     */
    private void parseNode(Node pNode, Map<String, Object> obj) {

        for (Map.Entry<String, Object> entry : obj.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            if (value instanceof Map) {
                Map<String, Object> _map = (Map<String, Object>) value;
                Node node = new Node();
                node.setKey(key);
                node.setMeta(_map);
                node.setRoot(root);
                node.setParent(pNode);
                pNode.getChilds().add(node);
                parseNode(node, _map);
            }
        }

    }

    /**
     * 形成data节点
     *
     * @param pNode
     */
    public void fillData(final Node pNode) {
        if (!"root".equals(pNode.getKey())) {
            pNode.excuteSql();
        }
        for (Node node : pNode.getChilds()) {
            if (pNode.getKey().endsWith("[]")) {
                for (Map map : (List<Map>) pNode.getData()) {
                    pNode.setTemData(map);
                    fillData(node);
                    map.put(node.getKey(), node.getData());
                }
            } else {
                pNode.setTemData((Map) pNode.getData());
                fillData(node);
                ((Map) pNode.getData()).put(node.getKey(), node.getData());

            }

        }
    }
}
